package com.example.rabbitmq.service.rabbitmq;


import com.example.rabbitmq.entity.User;
import com.example.rabbitmq.service.IRabbitmqService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;

@Service
@Slf4j
public class RabbitmqService implements IRabbitmqService {

    @Resource
    private RabbitTemplate rabbitTemplate;

    @Override
    public void sendWork() {
        for (int i = 0; i < 10; i++) {
            rabbitTemplate.convertAndSend("queue_work", "测试work模型: " + i);
        }
    }


    @Override
    public void sendPublish() {
        for (int i = 0; i < 5; i++) {
            // 使用 convertSendAndReceive 方法时的结果：使用此方法，只有确定消费者接收到消息，才会发送下一条信息，每条消息之间会有间隔时间
            // rabbitTemplate.convertSendAndReceive("exchange_fanout", "", "测试发布订阅模型：" + i);
            //使用 convertAndSend 方法时的结果：输出时没有顺序，不需要等待，直接运行
            rabbitTemplate.convertAndSend("exchange_fanout", "", "测试发布订阅模型：" + i);
        }
    }


    @Override
    public void sendTopic() {
        for (int i = 0; i < 10; i++) {
            if (i % 2 == 0) {
                rabbitTemplate.convertSendAndReceive("exchange_topic", "topic.km.topic", "测试发布订阅模型：" + i);
            } else {
                rabbitTemplate.convertSendAndReceive("exchange_topic", "topic.km", "测试发布订阅模型：" + i);
            }
        }
    }

    // 配置 confirm 机制
    private final RabbitTemplate.ConfirmCallback confirmCallback = new RabbitTemplate.ConfirmCallback() {
        /**
         * @param correlationData 消息相关的数据，一般用于获取 唯一标识 id
         * @param b true 消息确认成功，false 失败
         * @param s 确认失败的原因
         */
        @Override
        public void confirm(CorrelationData correlationData, boolean b, String s) {
            if (b) {
                log.info("confirm 消息确认成功...{}", correlationData.getId());
            } else {
                log.info("confirm 消息确认失败...{} cause: {}", correlationData.getId(), s);
            }
        }
    };

    @Override
    public void sendConfirm() {
        rabbitTemplate.convertAndSend("queue_confirm", new User(1, "km", "km123", new Date()), new CorrelationData("" + System.currentTimeMillis()));
        rabbitTemplate.setConfirmCallback(confirmCallback);
    }


    // 配置 return 消息机制
    private final RabbitTemplate.ReturnCallback returnCallback = new RabbitTemplate.ReturnCallback() {
        /**
         *  return 的回调方法（找不到路由才会触发）
         * @param message 消息的相关信息
         * @param i 错误状态码
         * @param s 错误状态码对应的文本信息
         * @param s1 交换机的名字
         * @param s2 路由的key
         */
        @Override
        public void returnedMessage(Message message, int i, String s, String s1, String s2) {
            log.info(String.valueOf(message));
            log.info(new String(message.getBody()));
            log.info(String.valueOf(i));
            log.info(s);
            log.info(s1);
            log.info(s2);
        }
    };

    // 测试return机制
    @Override
    public void sendReturn() {
        rabbitTemplate.setReturnCallback(returnCallback);
        rabbitTemplate.convertAndSend("exchange_return", "return.km.km", "测试 return 机制");
//        rabbitTemplate.convertAndSend("exchange_return", "return.km", "测试 return 机制");
    }


    @Override
    public void sendNeedAck() {
        rabbitTemplate.convertAndSend("exchange_ack","topic.ack","测试 消费者ack机制");
    }

    @Override
    public void sendDead() {
        rabbitTemplate.convertAndSend("exchange_dlx", "receive_key","测试死信队列");
    }
}
